/**
 * 
 */
package legumes.server.bll;

import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.List;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import legumes.client.services.ToExcellException;
import legumes.server.bll.users.Gpw;
import legumes.server.dal.DALLegumesServicesImpl;
import legumes.server.usl.services.MailStallParser;
import legumes.shared.domain.AdminException;
import legumes.shared.domain.Customer;
import legumes.shared.domain.CustomerDTO;
import legumes.shared.domain.CustomerRole;
import legumes.shared.domain.HomePlaceDelivery;
import legumes.shared.domain.LatLng;
import legumes.shared.domain.LoginException;
import legumes.shared.domain.MailStallParserException;
import legumes.shared.domain.NewProductMarket;
import legumes.shared.domain.Order;
import legumes.shared.domain.Product;
import legumes.shared.domain.ProductCategory;
import legumes.shared.domain.ProductVariety;
import legumes.shared.domain.SellSession;
import legumes.shared.domain.SellSessionForCustomer;
import legumes.shared.domain.Stall;
import legumes.shared.domain.Store;
import legumes.shared.domain.StoreException;
import legumes.shared.domain.UnicityViolationException;

public class BLLLegumesServicesImpl implements IBLLLegumesServices {
 
	private static IBLLLegumesServices s_instance;
	
	public static IBLLLegumesServices getInstance(){
		if(s_instance == null){
			s_instance = new BLLLegumesServicesImpl();
		}
		return s_instance;
	}
	
	private BLLLegumesServicesImpl(){
	}
	
	public void init(){
		DALLegumesServicesImpl.getInstance().init();
	}

	@Override
	public Customer getCustomer(long uuid_) {
		return DALLegumesServicesImpl.getInstance().getCustomer(uuid_);
	}

	@Override
	public SellSessionForCustomer getSellSessionForCustomer(CustomerDTO c_) {
		return DALLegumesServicesImpl.getInstance().getSellSessionForCustomer(c_);
	}

	@Override
	public SellSession getSellSession(long date_) {
		return DALLegumesServicesImpl.getInstance().getSellSession(date_);
	}

	@Override
	public void setStoreOpened(boolean b_) {
		DALLegumesServicesImpl.getInstance().setStoreOpened(b_);
	}

	@Override
	public boolean isStoreOpened() {
		return DALLegumesServicesImpl.getInstance().isStoreOpened();
	}

	@Override
	public long getOpenedSellSessionId() {
		return DALLegumesServicesImpl.getInstance().getOpenedSellSessionId();
	}

	@Override
	public List<Long> getSellSessionsDate() {
		return DALLegumesServicesImpl.getInstance().getSellSessionsDate();
	}

	@Override
	public List<Product> getProducts() {
		return DALLegumesServicesImpl.getInstance().getProducts();
	}

	@Override
	public boolean hasOrderConflict(CustomerDTO c_, long sellSessionId_, Order order_) {
		return DALLegumesServicesImpl.getInstance().hasOrderConflict(c_, sellSessionId_, order_);
	}
	
	@Override
	public Order save(CustomerDTO c_, long sellSessionId_, Order order_, boolean merge_)
			throws StoreException {
		return DALLegumesServicesImpl.getInstance().save(c_, sellSessionId_, order_, merge_);
	}

	@Override
	public Collection<Order> getOrders(long sellSessionId_) {
		return DALLegumesServicesImpl.getInstance().getOrders(sellSessionId_);
	}

	@Override
	public void save(Stall stall_) {
		DALLegumesServicesImpl.getInstance().save(stall_);
	}

	@Override
	public SellSession newSellSession(Store store_, long fromSellSessionId_) {
		return DALLegumesServicesImpl.getInstance().newSellSession(store_, fromSellSessionId_);
	}

	public void purgeSellSessions() {
		DALLegumesServicesImpl.getInstance().purgeSellSessions();
	}

	@Override
	public List<CustomerDTO> getCustomers() {
		return DALLegumesServicesImpl.getInstance().getCustomers();
	}
	
	@Override
	public Customer addCustomer(Customer c_) throws UnicityViolationException {
		Customer c= DALLegumesServicesImpl.getInstance().addCustomer(c_);
		
		if(c!=null){
			sendCustomerAccountCreationMail(c_);
		} else {
			//TODO manage error case
		}
		
		return c;
	}

	@Override
	public void removeCustomer(CustomerDTO c_, String customerId_) throws AdminException, LoginException {
		DALLegumesServicesImpl.getInstance().removeCustomer(c_, customerId_);
	}
	

	@Override
	public void changePassword(CustomerDTO c_, String password_, String newPassword_)
			throws LoginException {
		DALLegumesServicesImpl.getInstance().changePassword(c_, password_, newPassword_);
	}
	
	@Override
	public void setCustomerRole(String customerId_, CustomerRole role_) {
		DALLegumesServicesImpl.getInstance().setCustomerRole(customerId_, role_);
	}

	@Override
	public void setMessageStore(String message_) {
		DALLegumesServicesImpl.getInstance().setMessageStore(message_);
	}

	@Override
	public String getMessageStore() {
		return DALLegumesServicesImpl.getInstance().getMessageStore();
	}

	@Override
	public Stall parseStallMail(String mailContent_)
			throws MailStallParserException {
		MailStallParser mailStallParser = new MailStallParser(mailContent_);
		mailStallParser.parse();
		Stall stall = mailStallParser.getStall();
		return stall;
	}
	
	@Override
	public String generateOrdersReport(long sellSessionId_)
			throws ToExcellException {
		return DALLegumesServicesImpl.getInstance().generateOrdersReport(sellSessionId_);
	}

	@Override
	public Customer getCustomer(String name_) {
		return DALLegumesServicesImpl.getInstance().getCustomer(name_);
	}
	

	private boolean sendCustomerAccountCreationMail(Customer c_) {
		String userEmail = c_.getEmail();
		String userName = c_.getName();
		long uuidActivationAccount = c_.getActivationUuid();
		
		Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);

        String msgBody = "<H1>Bonjour " + userName + ", Veuillez activer votre compte." + 
        "</H1><a href=\"/UserAccountActivationService?uuid=" + uuidActivationAccount 
        + "&email=" + userEmail + "\">Activez votre compte.</a><a href=\"mailto:" + userEmail + "\">mail</a>";

        try {
            Message msg = new MimeMessage(session);
            msg.setFrom(new InternetAddress("admin@example.com", "Example.com Admin"));
            msg.addRecipient(Message.RecipientType.TO,
                             new InternetAddress(userEmail, "Mr. " + userName));
            msg.setSubject("Your Example.com account has been activated");
//            msg.setText(msgBody);
            msg.setContent(msgBody, "text/html");
            Transport.send(msg);

        } catch (AddressException e) {
            // ...
        	e.printStackTrace();
        } catch (MessagingException e) {
            // ...
        	e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return true;
	}

	private boolean sendEmailOnPasswordReset(Customer c_){
		//TODO
		return false;
	}
	
	private boolean sendEmailOnUserAccountActivated(Customer c_){
		//TODO
		String userEmail = c_.getEmail();
		String userName = c_.getName();
		
		Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);

        String msgBody = "<H1>Bonjour " + userName + ", Compte activ&eacute; avec succes.<a href=\"mailto:" + userEmail + "\">mail</a>";

        try {
            Message msg = new MimeMessage(session);
            msg.setFrom(new InternetAddress("admin@example.com", "Example.com Admin"));
            msg.addRecipient(Message.RecipientType.TO,
                             new InternetAddress(userEmail, "Mr. " + userName));
            msg.setSubject("Your Example.com account has been activated");
//            msg.setText(msgBody);
            msg.setContent(msgBody, "text/html");
            Transport.send(msg);

        } catch (AddressException e) {
            // ...
        } catch (MessagingException e) {
            // ...
        } catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return true;
	}

	@Override
	public boolean activateUserAccount(String email, String uuid) {
		Customer c = getCustomer(uuid);
		if(c==null && !c.getEmail().equalsIgnoreCase(email)){
			return false;
		}
		c.setActivationAccountDate(System.currentTimeMillis());
		DALLegumesServicesImpl.getInstance().saveCustomer(c);
		
		sendEmailOnUserAccountActivated(c);
		
		return true;
	}

	@Override
	public Customer getCustomerFromEmail(String login_) {
		return DALLegumesServicesImpl.getInstance().getCustomerFromEmail(login_);
	}

	@Override
	public void onCustomerLogon(Customer c_, String remoteHost_) {
		c_.setLastConnectionDate(System.currentTimeMillis());
		c_.setLastConnectionAddr(remoteHost_);
		
		DALLegumesServicesImpl.getInstance().saveCustomer(c_);
	}

	@Override
	public Product[] getProductsStartingWith(String prefix_) {
		return DALLegumesServicesImpl.getInstance().getProductsStartingWith(prefix_);
	}

	@Override
	public boolean validateNewProductMarket(NewProductMarket newProductMarket_) {
		return DALLegumesServicesImpl.getInstance().validateNewProductMarket(newProductMarket_);
	}

	@Override
	public Product addNewProductMarket(NewProductMarket newProductMarket_) {
		return DALLegumesServicesImpl.getInstance().addNewProductMarket(newProductMarket_);
	}

	@Override
	public ProductCategory[] getProductCategories() {
		return DALLegumesServicesImpl.getInstance().getProductCategories();
	}

	@Override
	public ProductVariety[] getProductVarities() {
		return DALLegumesServicesImpl.getInstance().getProductVarities();
	}

	@Override
	public String resetPassword(String email_) {
		Customer c = getCustomerFromEmail(email_);
		if( c!= null){
			c.setPassword( new Gpw().generate() );
			if( ! sendEmailOnPasswordReset(c) ){
				return "Une erreur est survenue lors de l'envoie de votre email de réinitialisastion de votre mot de passe. Veuillez essayer ultérieurement.";
			} else {
				DALLegumesServicesImpl.getInstance().updateCustomer(c);
			}
		} else {
			return "Email incorrect.";
		}
		return null;
	}

	@Override
	public List<Store> getUserStores(String userId_) {
		return DALLegumesServicesImpl.getInstance().getUserStores(userId_);
	}

	@Override
	public boolean removeStore(Store store_) {
		return DALLegumesServicesImpl.getInstance().removeStore(store_);
	}

	@Override
	public boolean isStoreNameExists(String storeName_) {
		return DALLegumesServicesImpl.getInstance().isStoreNameExists(storeName_);
	}

	@Override
	public Store addStore(Store storeToAdd) {
		if( isStoreNameExists(storeToAdd.getStoreName()) ){
			return null;
		}else {
			storeToAdd.setId(System.currentTimeMillis());
			return DALLegumesServicesImpl.getInstance().addStore(storeToAdd);
		}
	}

	@Override
	public List<Store> getStores(LatLng northEastBound_, LatLng southWestBound_) {
		return DALLegumesServicesImpl.getInstance().getStores(northEastBound_, southWestBound_);
	}

	@Override
	public void save(Store store_) {
		DALLegumesServicesImpl.getInstance().save(store_);
	}

}
